/*-
 * Copyright (c) 2010 mod_cfp team <mod-cfp@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: mod_cfp.h 170 2010-07-13 07:49:27Z mod.cfp $
 */

#ifndef _MOD_CFP_H
#define	_MOD_CFP_H

struct cfp_module;
struct cfp_sess;

typedef void cfp_attach_f(struct cfp_module *);
typedef void cfp_detach_f(struct cfp_module *);
typedef int cfp_lookup_f(struct cfp_sess *);
typedef int cfp_init_f(struct cfp_sess *);
typedef void cfp_fini_f(struct cfp_sess *);
typedef int cfp_start_f(struct cfp_sess *);

struct cfp_conf {
	unsigned		magic;
#define	CFP_CONF_MAGIC		0x65642220

	/* Called when the shared libray is loaded firstly */
	cfp_attach_f		*attach;
	/*
	 * Called during the web server is shutdowning.
	 */
	cfp_detach_f		*detach;
	/* Called when the newly request is accepted and headers are pared. */
	cfp_lookup_f		*lookup;
#define	CFP_MATCH_NONE		0
#define	CFP_MATCH_OK		1
	/*
	 * Called before the response is preparing.  This function only called
	 * once.  This callback is only called when the lookup was successful.
	 */
	cfp_init_f		*init;
	/*
	 * Called to prepare the response.  Your state machine could place
	 * here because it could be recalled depending on CFP_RET_... status.
	 * This callback is only called when the lookup was successful.
	 */
	cfp_start_f		*start;
	/*
	 * Called before the response is done to send. This callback is
	 * only called when the lookup was successful.
	 */
	cfp_fini_f		*fini;
};

#define	CFP_TXT_LEN(x)		((unsigned)((x)->e - (x)->b))
struct cfp_txt {
	const char		*b;
	const char		*e;
};

struct cfp_pair {
	struct cfp_txt		key;
	struct cfp_txt		value;
};

enum cfp_error {
	CFP_EINVAL,		/* Invalid argument */
	CFP_ENOENT,		/* No such entry, file or directory */
	CFP_EPERM,		/* Operation not permitted */
	CFP_ECONNRESET		/* Connection reset by peer */
};

struct cfp_sess {
	unsigned		magic;
#define	CFP_SESS_MAGIC		0x63206e6f

	struct cfp_conf		*conf;
	struct cfp_module	*module;
	enum cfp_error		errnum;
	unsigned		flags;
#define	CFP_SESS_FLAGS_MATCHED	(1 << 0)

	/* URL query string */
	struct cfp_pair		*query;
	unsigned		nquery;
	/* URL query string for POST */
	struct cfp_pair		*post_query;
	unsigned		npost_query;

	/* server argument; don't use this at .so */
	void			*srv_arg;
	/* opaque type for .so */
	void			*arg;
	int			fd;
};

struct cfp_module {
	unsigned		magic;
#define	CFP_MODULE_MAGIC	0x554e0945

	/* server argument; don't use this at .so */
	void			*srv_arg;
	/* opaque type for .so */
	void			*arg;
};

/*
 * The return code from the .so file.
 */
#define	CFP_RET_DONE		(1 << 0)
#define	CFP_RET_SOCKET_READABLE	(1 << 1)
#define	CFP_RET_SOCKET_WRITABLE	(1 << 2)
#define	CFP_RET_DISK_READ	(1 << 3)
#define	CFP_RET_DISK_WRITE	(1 << 4)
#define	CFP_RET_CONTINUE	(1 << 5)
#define	CFP_RET_ERROR		(1 << 6)

int	cfp_fprintf(struct cfp_sess *, const char *fmt, ...);
void	cfp_log(struct cfp_module *, const char *fmt, ...);
int	cfp_get_request_origuri(struct cfp_sess *, struct cfp_txt *);
int	cfp_get_requrl(struct cfp_sess *, struct cfp_txt *);
int	cfp_get_querystring(struct cfp_sess *, struct cfp_txt *);
int	cfp_get_request_method(struct cfp_sess *, struct cfp_txt *);
int	cfp_get_postquery(struct cfp_sess *, const char *, struct cfp_txt *);
int	cfp_get_query(struct cfp_sess *, const char *, struct cfp_txt *);
int	cfp_getenv(struct cfp_sess *, const char *, struct cfp_txt *);
int	cfp_get_header(struct cfp_sess *, const char *, struct cfp_txt *);
int	cfp_set_header(struct cfp_sess *, const char *, const char *);
int	cfp_set_status(struct cfp_sess *, int);

#endif
